package com.itestor.iptv.global.utils;

import net.sf.navigator.displayer.MenuDisplayerMapping;
import net.sf.navigator.displayer.MessageResourcesMenuDisplayer;
import net.sf.navigator.menu.MenuComponent;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;

import org.apache.commons.lang.StringUtils;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;

/**
 * 基于Struts Menu的Ext Js 2的扩展.
 * @author TrueOrFalse.Yuan
 */
public class ExtJSMenuDisplayer extends MessageResourcesMenuDisplayer {

	private static final String TAB = "    "; // four spaces

	private static final String HX_MENU_START = "\n<!-- Hua-Xia Menu Base On ExtJS - Start -->\n";

	private static final String HX_MENU_END = "\n<!-- Hua-Xia Menu Base On ExtJS - End -->\n";;

	private static final String STYLE_START = "\n<style type=\"text/css\" media=\"screen\">\n";

	private static final String STYLE_END = "\n</style>\n";

	private static final String SCRIPT_START = "\n<script type=\"text/javascript\">\n<!--";

	private static final String SCRIPT_END = "//-->\n</script>\n";

	private static final String EXTJS_START = "\nExt.onReady(function(){\n";

	private static final String EXTJS_END = "\n});\n";

	private static MessageFormat styleMenuItemMessage = new MessageFormat("\n.menu-item-icon-{0} '{' background-image: {1} !important; '}'\n");

	private static MessageFormat scriptTopMenuMessage = new MessageFormat(
			"\nvar menu_{0} = new Ext.Toolbar('{' id: ''menu-{0}'', items: [{1}] '}');\nmenu_{0}.render(''menu-{0}-container'');\n");

	private static MessageFormat scriptSubMenuMessage = new MessageFormat("\nvar menu_{0} = new Ext.menu.Menu('{' id: ''menu-{0}'''}');\n");

	private String id;

	private String style;

	private Collection<String> topItems = new ArrayList<String>();

	public void init(PageContext pageContext, MenuDisplayerMapping mapping) {
		super.init(pageContext, mapping);
		id = (String) pageContext.getAttribute("menuId");
		try {
			out.print(HX_MENU_START);
			out.print(SCRIPT_START);
			out.print(EXTJS_START);
		} catch (Exception e) {
			log.error(e.getMessage());
		}
	}

	public void display(MenuComponent menu) throws JspException, IOException {
		buildMenu(menu);
	}

	public void end(PageContext context) {
		try {
			out.print(buildTopMenuScript());
			out.print(EXTJS_END);
			out.print(SCRIPT_END);

			out.print(STYLE_START);
			if (style != null) {
				out.print(style);
			}
			out.print(STYLE_END);

			out.print(HX_MENU_END);
		} catch (Exception e) {
			log.error(e.getMessage());
		} finally {
			this.id = null;
		}
	}

	protected void buildMenu(MenuComponent menu) throws IOException {
		style += buildMenuStyle(menu, 0, isAllowed(menu));
		if (isAllowed(menu)) {
			topItems.add(menu.getName());
		}
		out.print(buildSubMenuScript(menu, 0, isAllowed(menu)));
	}

	protected String buildMenuStyle(MenuComponent menu, int deep, boolean allowed) {
		String menuStyle = "";
		if (allowed) {
			String sCurrentDeepTab = "";
			for (int i = 0; i < deep; i++) {
				sCurrentDeepTab += TAB;
			}
			log.debug(sCurrentDeepTab + "Creating the Style of the Menu-Item-" + menu.getName() + "...");
			if (menu.getImage() != null) {
				menuStyle = sCurrentDeepTab + styleMenuItemMessage.format(getStyleArgs(menu));
			}
			MenuComponent[] subMenus = menu.getMenuComponents();
			if (subMenus.length > 0) {
				for (int i = 0; i < subMenus.length; i++) {
					menuStyle += buildMenuStyle(subMenus[i], deep + 1, isAllowed(subMenus[i]));
				}
			} else {
			}
		}
		return menuStyle == null ? "" : menuStyle;
	}

	protected String buildTopMenuScript() {
		String menuScript = "";
		menuScript += scriptTopMenuMessage.format(getScriptTopMenuArgs());
		return menuScript;
	}

	protected String buildSubMenuScript(MenuComponent menu, int deep, boolean allowed) {
		String menuScript = "";
		if (allowed) {
			String sCurrentDeepTab = "";
			for (int i = 0; i < deep; i++) {
				sCurrentDeepTab += TAB;
			}
			MenuComponent[] subMenus = menu.getMenuComponents();
			if (deep > 0) {
				if (subMenus.length > 0) {
					log.debug(sCurrentDeepTab + "Create SubMenu - " + menu.getName());
					menuScript += sCurrentDeepTab + scriptSubMenuMessage.format(getScriptSubMenuArgs(menu));
					for (int i = 0; i < subMenus.length; i++) {
						menuScript += buildSubMenuScript(subMenus[i], deep + 1, isAllowed(subMenus[i]));
					}
					log.debug(sCurrentDeepTab + "Create SubMenuItem - " + menu.getName() + " with SubMenu - " + menu.getName());
					if (menu.getImage() == null) {
						if (StringUtils.isEmpty(menu.getAction())) {
							menuScript += sCurrentDeepTab + scriptSubMenuItemWithMenuMessage.format(getScriptSubMenuItemArgs(menu));
						} else {
							menuScript += sCurrentDeepTab + scriptSubMenuLinkWithMenuMessage.format(getScriptSubMenuItemArgs(menu));
						}
					} else {
						if (StringUtils.isEmpty(menu.getAction())) {
							menuScript += sCurrentDeepTab + scriptSubIconMenuItemWithMenuMessage.format(getScriptSubMenuItemArgs(menu));
						} else {
							menuScript += sCurrentDeepTab + scriptSubIconMenuLinkWithMenuMessage.format(getScriptSubMenuItemArgs(menu));
						}
					}
				} else {
					log.debug(sCurrentDeepTab + "Create SubMenuItem - " + menu.getName());
					if (menu.getImage() == null) {
						if (StringUtils.isEmpty(menu.getAction())) {
							menuScript += sCurrentDeepTab + scriptSubMenuItemWithoutMenuMessage.format(getScriptSubMenuItemArgs(menu));
						} else {
							menuScript += sCurrentDeepTab + scriptSubMenuLinkWithoutMenuMessage.format(getScriptSubMenuItemArgs(menu));
						}
					} else {
						if (StringUtils.isEmpty(menu.getAction())) {
							menuScript += sCurrentDeepTab + scriptSubIconMenuItemWithoutMenuMessage.format(getScriptSubMenuItemArgs(menu));
						} else {
							menuScript += sCurrentDeepTab + scriptSubIconMenuLinkWithoutMenuMessage.format(getScriptSubMenuItemArgs(menu));
						}
					}
				}
			} else {
				if (subMenus.length > 0) {
					log.debug(sCurrentDeepTab + "Create SubMenu - " + menu.getName());
					menuScript += sCurrentDeepTab + scriptSubMenuMessage.format(getScriptSubMenuArgs(menu));
					for (int i = 0; i < subMenus.length; i++) {
						menuScript += buildSubMenuScript(subMenus[i], deep + 1, isAllowed(subMenus[i]));
					}
					log.debug(sCurrentDeepTab + "Create TopMenuItem - " + menu.getName() + " with SubMenu - " + menu.getName());
					if (menu.getImage() == null) {
						if (StringUtils.isEmpty(menu.getAction())) {
							menuScript += sCurrentDeepTab + scriptTopMenuItemWithMenuMessage.format(getScriptTopMenuItemArgs(menu));
						} else {
							menuScript += sCurrentDeepTab + scriptTopMenuLinkWithMenuMessage.format(getScriptTopMenuItemArgs(menu));
						}
					} else {
						if (StringUtils.isEmpty(menu.getAction())) {
							menuScript += sCurrentDeepTab + scriptTopIconMenuItemWithMenuMessage.format(getScriptTopMenuItemArgs(menu));
						} else {
							menuScript += sCurrentDeepTab + scriptTopIconMenuLinkWithMenuMessage.format(getScriptTopMenuItemArgs(menu));
						}
					}
				} else {
					if (menu.getImage() == null) {
						if (StringUtils.isEmpty(menu.getAction())) {
							menuScript += sCurrentDeepTab + scriptTopMenuItemWithoutMenuMessage.format(getScriptTopMenuItemArgs(menu));
						} else {
							menuScript += sCurrentDeepTab + scriptTopMenuLinkWithoutMenuMessage.format(getScriptTopMenuItemArgs(menu));
						}
					} else {
						if (StringUtils.isEmpty(menu.getAction())) {
							menuScript += sCurrentDeepTab + scriptTopIconMenuItemWithoutMenuMessage.format(getScriptTopMenuItemArgs(menu));
						} else {
							menuScript += sCurrentDeepTab + scriptTopIconMenuLinkWithoutMenuMessage.format(getScriptTopMenuItemArgs(menu));
						}
					}
				}
			}
		}
		return menuScript == null ? "" : menuScript;
	}

	protected String[] getScriptTopMenuArgs() {
		String[] args = new String[2];
		args[0] = (id == null ? "ext" : id);
		args[1] = "";
		for (String item : topItems) {
			args[1] += "menu_item_" + item + ", ";
		}
		args[1] = args[1].substring(0, args[1].length() - 2);
		return args;
	}

	private static MessageFormat scriptTopMenuItemWithMenuMessage = new MessageFormat(
			"\nvar menu_item_{0} = new Ext.Toolbar.Button('{' id: ''menu-item-{0}'', text: ''{1}'', menu: {2} '}');\n");

	private static MessageFormat scriptTopMenuItemWithoutMenuMessage = new MessageFormat(
			"\nvar menu_item_{0} = new Ext.Toolbar.Button('{' id: ''menu-item-{0}'', text: ''{1}'' '}');\n");

	private static MessageFormat scriptTopIconMenuItemWithMenuMessage = new MessageFormat(
			"\nvar menu_item_{0} = new Ext.Toolbar.Button('{' id: ''menu-item-{0}'', text: ''{1}'', menu: {2}, iconCls: ''menu-item-icon-{0}'' '}');\n");

	private static MessageFormat scriptTopIconMenuItemWithoutMenuMessage = new MessageFormat(
			"\nvar menu_item_{0} = new Ext.Toolbar.Button('{' id: ''menu-item-{0}'', text: ''{1}'', iconCls: ''menu-item-icon-{0}'' '}');\n");

	private static MessageFormat scriptTopMenuLinkWithMenuMessage = new MessageFormat(
			"\nvar menu_item_{0} = new Ext.Toolbar.Button('{' id: ''menu-item-{0}'', text: ''{1}'', menu: {2}, url: ''{3}'', target: ''{4}'', handler: menu_navigate '}');\n");

	private static MessageFormat scriptTopMenuLinkWithoutMenuMessage = new MessageFormat(
			"\nvar menu_item_{0} = new Ext.Toolbar.Button('{' id: ''menu-item-{0}'', text: ''{1}'', url: ''{2}'', target: ''{3}'', handler: menu_navigate '}');\n");

	private static MessageFormat scriptTopIconMenuLinkWithMenuMessage = new MessageFormat(
			"\nvar menu_item_{0} = new Ext.Toolbar.Button('{' id: ''menu-item-{0}'', text: ''{1}'', menu: {2}, url: ''{3}'', target: ''{4}'', handler: menu_navigate, iconCls: ''menu-item-icon-{0}'' '}');\n");

	private static MessageFormat scriptTopIconMenuLinkWithoutMenuMessage = new MessageFormat(
			"\nvar menu_item_{0} = new Ext.Toolbar.Button('{' id: ''menu-item-{0}'', text: ''{1}'', url: ''{2}'', target: ''{3}'', handler: menu_navigate, iconCls: ''menu-item-icon-{0}'' '}');\n");

	protected String[] getScriptTopMenuItemArgs(MenuComponent menu) {
		String[] args;
		if (StringUtils.isEmpty(menu.getAction())) {
			if (menu.getMenuComponents().length > 0) {
				args = new String[3];
				args[2] = "menu_" + menu.getName();
			} else {
				args = new String[2];
			}
		} else {
			if (menu.getMenuComponents().length > 0) {
				args = new String[5];
				args[2] = "menu_" + menu.getName();
				args[3] = menu.getAction();
				args[4] = getTarget(menu);
			} else {
				args = new String[4];
				args[2] = menu.getAction();
				args[3] = getTarget(menu);
			}
		}
		args[0] = menu.getName();
		args[1] = getMessage(menu.getTitle());
		return args;
	}

	protected String[] getScriptSubMenuArgs(MenuComponent menu) {
		String[] args = new String[1];
		args[0] = menu.getName();
		return args;
	}

	private static MessageFormat scriptSubMenuItemWithMenuMessage = new MessageFormat("\nvar menu_item_{0} = menu_{1}.add('{' text: ''{2}'', menu: {3} '}');\n");

	private static MessageFormat scriptSubMenuItemWithoutMenuMessage = new MessageFormat("\nvar menu_item_{0} = menu_{1}.add('{' text: ''{2}'' '}');\n");

	private static MessageFormat scriptSubIconMenuItemWithMenuMessage = new MessageFormat(
			"\nvar menu_item_{0} = menu_{1}.add('{' text: ''{2}'', menu: {3}, iconCls: ''menu-item-icon-{0}'' '}');\n");

	private static MessageFormat scriptSubIconMenuItemWithoutMenuMessage = new MessageFormat(
			"\nvar menu_item_{0} = menu_{1}.add('{' text: ''{2}'', iconCls: ''menu-item-icon-{0}'' '}');\n");

	private static MessageFormat scriptSubMenuLinkWithMenuMessage = new MessageFormat(
			"\nvar menu_item_{0} = menu_{1}.add('{' text: ''{2}'', menu: {3}, url: ''{4}'', target: ''{5}'', handler: menu_navigate '}');\n");

	private static MessageFormat scriptSubMenuLinkWithoutMenuMessage = new MessageFormat(
			"\nvar menu_item_{0} = menu_{1}.add('{' text: ''{2}'', url: ''{3}'', target: ''{4}'', handler: menu_navigate '}');\n");

	private static MessageFormat scriptSubIconMenuLinkWithMenuMessage = new MessageFormat(
			"\nvar menu_item_{0} = menu_{1}.add('{' text: ''{2}'', menu: {3}, url: ''{4}'', target: ''{5}'', handler: menu_navigate, iconCls: ''menu-item-icon-{0}'' '}');\n");

	private static MessageFormat scriptSubIconMenuLinkWithoutMenuMessage = new MessageFormat(
			"\nvar menu_item_{0} = menu_{1}.add('{' text: ''{2}'', url: ''{3}'', target: ''{4}'', handler: menu_navigate, iconCls: ''menu-item-icon-{0}'' '}');\n");

	protected String[] getScriptSubMenuItemArgs(MenuComponent menu) {
		String[] args;
		if (StringUtils.isEmpty(menu.getAction())) {
			if (menu.getMenuComponents().length > 0) {
				args = new String[4];
				args[3] = "menu_" + menu.getName();
			} else {
				args = new String[3];
			}
		} else {
			if (menu.getMenuComponents().length > 0) {
				args = new String[6];
				args[3] = "menu_" + menu.getName();
				args[4] = menu.getAction();
				args[5] = getTarget(menu);
			} else {
				args = new String[5];
				args[3] = menu.getAction();
				args[4] = getTarget(menu);
			}
		}
		args[0] = menu.getName();
		args[1] = menu.getParent().getName();
		args[2] = getMessage(menu.getTitle());
		return args;
	}

	protected String[] getStyleArgs(MenuComponent menu) {
		if (menu.getImage() == null) {
			return null;
		}
		String[] args = new String[2];
		args[0] = menu.getName();
		args[1] = "url(" + menu.getImage() + ")";

		return args;
	}

	protected String getParentName(MenuComponent menu) {
		String name;

		if (menu.getParent() == null) {
			name = "";
		} else {
			name = menu.getParent().getName();
		}

		return name;
	}

	protected String getTarget(MenuComponent menu) {
		String theTarget = super.getTarget(menu);
		if (theTarget == null) {
			theTarget = EMPTY;
		}
		return theTarget;
	}
}
